package logic;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import weka.classifiers.Classifier;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.lazy.IBk;
import weka.classifiers.trees.Id3;
import weka.core.Instances;
import weka.core.converters.ArffSaver;
import weka.core.converters.CSVLoader;
import weka.core.converters.ConverterUtils.DataSource;
import weka.filters.Filter;
import weka.filters.supervised.attribute.AttributeSelection;
import weka.filters.unsupervised.attribute.Discretize;
import weka.filters.unsupervised.attribute.Normalize;
import weka.filters.unsupervised.attribute.ReplaceMissingValues;

public class Loader {
    public static final int MODEL_MUSHROOM_KNN = 0;
    public static final int MODEL_MUSHROOM_NB = 1;
    public static final int MODEL_MUSHROOM_ID3 = 2;
    public static final int MODEL_WEKA_KNN = 3;
    public static final int MODEL_WEKA_NB = 4;
    public static final int MODEL_WEKA_ID3 = 5;
    
    public static final int UNSUPERVISED_DISCRETIZE = 1;
    public static final int UNSUPERVISED_NORMALIZE = 2;
    public static final int UNSUPERVISED_REPLACE_MISSING_VALUES = 3;
    public static final int SUPERVISED_ATTRIBUTE_SELECTION = 4;
    
    public static Instances load(String file) {
        Instances i = null;
        try {
            i = DataSource.read(file);
            i.setClassIndex(i.numAttributes() - 1);
        } catch (Exception e) {
            System.err.println("IOException in Loader.load()");
        }
        
        return i;
    }
    
    public static void convert(String csv) {
        CSVLoader csvLoader = new CSVLoader();
        Instances i = null;
        
        try {
            csvLoader.setSource(new File(csv));
            i = csvLoader.getDataSet();
            
            String newFile = csv.substring(0, csv.length()-3) + "arff";
            saveInstances2arff(i, newFile);
            System.out.println(csv + " converted successfully to " + newFile);
        } catch (IOException e) {
            System.err.println("IOException in Loader.convert()");
        }
    }
    
    public static void saveInstances2arff(Instances i, String file) {
        ArffSaver saver = new ArffSaver();
        try {
            saver.setInstances(i);
            saver.setFile(new File(file));
            saver.writeBatch();
        } catch (IOException e) {
            System.out.println("IOException in Loader.saveInstances2arff()");
        }
    }
    
    public static String getExt(String file) {
        return (file.substring(file.lastIndexOf(".")));
    }
    
    public static void saveModel(Classifier cls, int model, String filePath) {
        
        try {
            switch (model) {
                case MODEL_MUSHROOM_KNN:
                    weka.core.SerializationHelper.write(filePath, (MushroomkNN)cls);
                    break;
                case MODEL_MUSHROOM_NB:
                    weka.core.SerializationHelper.write(filePath, (MushroomNB)cls);
                    break;
                case MODEL_MUSHROOM_ID3:
                    weka.core.SerializationHelper.write(filePath, (MushroomID3)cls);
                    break;
                case MODEL_WEKA_KNN:
                    weka.core.SerializationHelper.write(filePath, (IBk)cls);
                    break;
                case MODEL_WEKA_NB:
                    weka.core.SerializationHelper.write(filePath, (NaiveBayes)cls);
                    break;
                case MODEL_WEKA_ID3:
                    weka.core.SerializationHelper.write(filePath, (Id3)cls);
                    break;
            }
        } catch (Exception e) {
            System.out.println("Exception in Loader.saveModel()");
        }
    }
    
    public static Classifier loadModel(String filePath) {
        Classifier cls = null;
        try {
            cls = (Classifier)weka.core.SerializationHelper.read(filePath);
        } catch (Exception e) {
            System.err.println("Exception in MushroomNB.loadModel()");
        }
        
        return cls;
    }
    
    public static Instances preProcess(Instances data, int opt) {
        // preProcess function generates an Instances which has been pre-processed
        // Attribute dsc :
        // 1. data, contains an instances which want to be pre-processed
        // 2. opt, contains a number refer to which pre-process method to be used
        // 3. deleteattr[], contains a set of attribute's number which want to be deleted
        
        Instances value = null;

        try {
            switch (opt) {
                case UNSUPERVISED_DISCRETIZE:
                    Discretize dist = new Discretize();
                    dist.setIgnoreClass(false);
                    dist.setInputFormat(data);
                    value = Filter.useFilter(data, dist);
                    break;
                case UNSUPERVISED_NORMALIZE:
                    Normalize norm = new Normalize();
                    norm.setIgnoreClass(false);
                    norm.setInputFormat(data);
                    value = Filter.useFilter(data, norm);
                    break;
                case UNSUPERVISED_REPLACE_MISSING_VALUES:
                    ReplaceMissingValues rmv = new ReplaceMissingValues();
                    rmv.setIgnoreClass(false);
                    rmv.setInputFormat(data);
                    value = Filter.useFilter(data, rmv);
                    break;
                case SUPERVISED_ATTRIBUTE_SELECTION:
                    AttributeSelection attrs = new AttributeSelection();
                    attrs.setInputFormat(data);
                    value = Filter.useFilter(data, attrs);
                    break;
                default:
                    System.out.println("Out of Range\n");
            }
        } catch (Exception e) {
            Logger.getLogger(Loader.class.getName()).log(Level.SEVERE,null,e);
        }
        
        return value;        
    }
    
    public static void main(String[] args) {
        convert("C:\\Program Files\\Weka-3-6\\mushroom.csv");
    }
}
